home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / PCGPEV10.ZIP / CPUTYPE.TXT < prev    next >
Text File  |  1994-05-10  |  8KB  |  246 lines

  1.                    ┌────────────────────────────┐
  2.                    │ Testing the Intel CPU Type │
  3.                    └────────────────────────────┘
  4.  
  5.             Written for the PC-GPE by Mark Feldman
  6.             e-mail address : u914097@student.canberra.edu.au
  7.                              myndale@cairo.anu.edu.au
  8.  
  9.            ┌───────────────────────────────────────────┐
  10.            │      THIS FILE MAY NOT BE DISTRIBUTED     │
  11.            │ SEPERATE TO THE ENTIRE PC-GPE COLLECTION. │
  12.            └───────────────────────────────────────────┘
  13.  
  14.  
  15. ┌────────────┬───────────────────────────────────────────────────────────────
  16. │ Disclaimer │
  17. └────────────┘
  18.  
  19. I assume no responsibility whatsoever for any effect that this file, the
  20. information contained therein or the use thereof has on you, your sanity,
  21. computer, spouse, children, pets or anything else related to you or your
  22. existance. No warranty is provided nor implied with this information.
  23.  
  24. ┌──────────────┬─────────────────────────────────────────────────────────────
  25. │ Introduction │
  26. └──────────────┘
  27.  
  28. Believe it or not there are people in the world who still own 8088s! Heck I
  29. only just upgraded my 286 to a 486SUX33 a couple of months ago.
  30.  
  31. As we all know, 286's and below just don't make the cut anymore, and even
  32. 386's are becoming a thing of the past. Personally I think a program should
  33. politely tell someone they are a phleb rather than unceremoniously hanging
  34. their machine for them.
  35.  
  36. This text file will show one mothed of detecting the CPU type. Unfortunately
  37. I don't have a Pentium op code list so it'll only detect up to a 486.
  38.  
  39. Most of the information in this file came from a well documented assembly
  40. program available on various ftp sites called 80486.asm, written by Robert
  41. Collins. I tried calling Robert for permission to use his original file, but
  42. he appears to have moved house.
  43.  
  44. ┌────────┬───────────────────────────────────────────────────────────────────
  45. │ Method │
  46. └────────┘
  47.  
  48. 80186 chips and higher generate an interrupt 6 when they come across an
  49. instruction they don't support, this provides us with a real simple method
  50. of determining the cpu type (coupled with the trap interrupt it would
  51. conceivably also allow us to write a Pentium emulator for the 80286, but
  52. that's another story). We simply have to try execting a 486 command, if it
  53. causes an interrupt 6 then we know the machine is a 386 or lower.
  54.  
  55. The op codes used in the program below all modify the dx register.
  56.  
  57.      ┌───────────────────────────────────────────────────────────────┐
  58.      │  Op Code           Machine Language Bytes   Supported by      │
  59.      ├───────────────────────────────────────────────────────────────┤
  60.      │  shl  dx, 5               C1 E2 05           80186 and higher │
  61.      │  smsw dx                  0F 01 E2           80286 and higher │
  62.      │  mov  edx, cr0            0F 20 C2           80386 and higher │
  63.      │  xadd dx, dx              0F C1 D2           80486 and higher │
  64.      └───────────────────────────────────────────────────────────────┘
  65.  
  66. When an interrupt 6 is generated you have to modify the value of the IP
  67. register which was pushed onto the stack when the interrupt occurred,
  68. otherwise the CPU will go back to it after the interrupt and keep trying
  69. to execute it. Each of the instructions in the table above are 3 bytes long
  70. so our interrupt handler can simply add 3 to the IP value on the stack.
  71.  
  72. Identifying an 8088 chip is even simpler. If you push the SP register onto
  73. the stack the 8088 increments the SP value before it pushes it, the other
  74. chips all increment it afterwards. So to test for the presence of an 8088
  75. push SP onto the stack and pop it off into another variable, say AX. If AX
  76. and SP are not equal then the chip is an 8088.
  77.  
  78. Keep in mind that you *MUST* check for the presence of an 8088 before
  79. doing anything else. Attempting to execute an invalid op code on an 8088
  80. will cause it to hang. Each of the functions in the unit below check for
  81. an 8088 first to prevent this happening.
  82.  
  83. ┌────────────────────────────────────┬───────────────────────────────────────
  84. │ A Pascal Unit to Test the CPU Type │
  85. └────────────────────────────────────┘
  86.  
  87. The following pascal unit contains some functions your program can use to
  88. make sure it's running on the right kind of machine. If your program will
  89. only work on a 386 and higher (for example) then put this unit first in your
  90. Uses clause and modify the unit's initialization code to terminate the
  91. program if the wrong CPU type is detected. The unit's current initialization
  92. simply test the CPU type and store it in the 'cpu' variable.
  93.  
  94. {
  95.  
  96.   CPUTYPE - A Pascal Unit to Test the CPU Type
  97.             By Mark Feldman u914097@student.canberra.edu
  98.                             myndale@cairo.anu.edu.au
  99.  
  100.             Based on an original assembly program by Robert Collins.
  101.  
  102.  
  103. }
  104.  
  105.  
  106. Unit CPUTYPE;
  107.  
  108.  
  109. Interface
  110.  
  111. const CPU_8088    =  0;
  112.       CPU_80186   =  1;
  113.       CPU_80286   =  2;
  114.       CPU_80386   =  3;
  115.       CPU_80486   =  4;
  116.       CPU_UNKNOWN = -1;
  117.  
  118. { The cpu variable is initialised to the cpu type }
  119. var cpu : integer;
  120.  
  121. { Isa8088 returns true only if cpu is an 8088 or 8086 }
  122. function Isa8088 : boolean;
  123.  
  124. { Isa80186 returns true if cpu is an 80186 or higher }
  125. function Isa80186 : boolean;
  126.  
  127. { Isa80286 returns true if cpu is an 80286 or higher }
  128. function Isa80286 : boolean;
  129.  
  130. { Isa80386 returns true if cpu is an 80386 or higher }
  131. function Isa80386 : boolean;
  132.  
  133. { Isa80486 returns true if cpu is an 80486 or higher }
  134. function Isa80486 : boolean;
  135.  
  136.  
  137.  
  138.  
  139. Implementation
  140.  
  141. Uses Dos;
  142.  
  143. var OldIntr6Handler : procedure;
  144.       valid_op_code : boolean;
  145.  
  146. procedure Intr6Handler;
  147. interrupt;
  148. begin
  149.   valid_op_code := false;
  150.  
  151.   { Stoopid TP7 won't let me modify IP directly }
  152.   asm
  153.     add word ptr ss:[bp + 18], 3
  154.   end;
  155. end;
  156.  
  157. function Isa8088 : boolean;
  158. var sp1, sp2 : word;
  159. begin
  160.   asm
  161.     mov sp1, sp
  162.     push sp
  163.     pop sp2
  164.   end;
  165.   if sp1 <> sp2 then
  166.     Isa8088 := true
  167.   else
  168.     Isa8088 := false;
  169. end;
  170.  
  171. function Isa80186 : boolean;
  172. begin
  173.   if Isa8088 then
  174.     Isa80186 := false
  175.   else
  176.     begin
  177.       valid_op_code := true;
  178.       GetIntVec(6, @OldIntr6Handler);
  179.       SetIntVec(6, Addr(Intr6Handler));
  180.       inline($C1/$E2/$05);  { shl dx, 5 }
  181.       SetIntVec(6, @OldIntr6Handler);
  182.       Isa80186 := valid_op_code;
  183.     end;
  184. end;
  185.  
  186. function Isa80286 : boolean;
  187. begin
  188.   if Isa8088 then
  189.     Isa80286 := false
  190.   else
  191.     begin
  192.       valid_op_code := true;
  193.       GetIntVec(6, @OldIntr6Handler);
  194.       SetIntVec(6, Addr(Intr6Handler));
  195.       inline($0F/$01/$E2);  { smsw dx }
  196.       SetIntVec(6, @OldIntr6Handler);
  197.       Isa80286 := valid_op_code;
  198.     end;
  199. end;
  200.  
  201. function Isa80386 : boolean;
  202. begin
  203.   if Isa8088 then
  204.     Isa80386 := false
  205.   else
  206.     begin
  207.       valid_op_code := true;
  208.       GetIntVec(6, @OldIntr6Handler);
  209.       SetIntVec(6, Addr(Intr6Handler));
  210.       inline($0F/$20/$C2);  { mov edx, cr0 }
  211.       SetIntVec(6, @OldIntr6Handler);
  212.       Isa80386 := valid_op_code;
  213.     end;
  214. end;
  215.  
  216. function Isa80486 : boolean;
  217. begin
  218.   if Isa8088 then
  219.     Isa80486 := false
  220.   else
  221.     begin
  222.       valid_op_code := true;
  223.       GetIntVec(6, @OldIntr6Handler);
  224.       SetIntVec(6, Addr(Intr6Handler));
  225.       inline($0F/$C1/$D2);  { xadd dx, dx }
  226.       SetIntVec(6, @OldIntr6Handler);
  227.       Isa80486 := valid_op_code;
  228.     end;
  229. end;
  230.  
  231.  
  232. begin
  233.   if Isa8088 then
  234.     cpu := CPU_8088
  235.   else if Isa80486 then
  236.     cpu := CPU_80486
  237.   else if Isa80386 then
  238.     cpu := CPU_80386
  239.   else if Isa80286 then
  240.     cpu := CPU_80286
  241.   else if Isa80186 then
  242.     cpu := CPU_80186
  243.   else
  244.     cpu := CPU_UNKNOWN;
  245. end.
  246.